package com.sticktogether.services;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import com.sticktogether.MapViewActivity;
import com.sticktogether.R;
import com.sticktogether.location.MyLocation;
import com.sticktogether.server.ServerCommunication;

public class GpsService extends Service {
	
	private static final int ID = 1;
	LocationManager mlocManager;
	LocationListener mlocListener;
	public MyLocation mCurrentLocation = new MyLocation(new Location(""));	
	private long lastUpdateTime = 0;
	private boolean inGpsMode;
	private boolean inMapView;
	
	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return null;
	}
	
	@Override
	public void onCreate() {

		ServerCommunication.currentService = this;
		mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE); 
		mlocListener = new LocationListener() {
			
			public void onLocationChanged(Location location) {
				// when was the last position sent to the server
				long timeSincelastUpdate = (System.currentTimeMillis()-lastUpdateTime);
				
		    	float intervall;
		    	float frequency;
		    	if(inGpsMode || inMapView) {
		    		intervall = 1;
		    		frequency = 5000;
		    	}
		    	else {
					//get shared settings
			    	Context context = getApplicationContext();
			    	SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
			    	intervall = Float.parseFloat(sharedPref.getString("track_frequency", "20"));
			    	frequency = Float.parseFloat(sharedPref.getString("sync_frequency", "60000"));
		    	}
				
			    synchronized (mCurrentLocation) {
			    	//We have received our very first position, so save it!
			    	if (lastUpdateTime == 0 ) {
						update(location);
						Log.i("gps service", "Got a first location from " + location.getProvider() + ", saving it.");
			        }
					
			    	//We have not updated our position for over 50 minutes, so do it now!
					else if(timeSincelastUpdate > 3000000) {
						update(location);
						Log.i("gps service", "Got a new location from " + location.getProvider() + ", not updated for over 50 minutes, saving it.");
					}
					
					//We have not updated our position longer than the user has chosen in settings.
					//or if we are in GPS-mode or map view: not longer than 5 seconds.
					//If we have a gps position, always take it (if it is better).
			        else if (timeSincelastUpdate > frequency || location.getProvider().equals(LocationManager.GPS_PROVIDER)){
			            // check if the new position is better than the one we already have.
			        	if (mCurrentLocation.isBetterLocation(location, intervall)){
			        		//Ok, this position seems to be better, saving it... 
			        		update(location);
			        		Log.i("gps service", "Got a new location from " + location.getProvider() + ", saving it.");
		                }
			        	else {
			        		Log.e("gps service", "Got a new location from " + location.getProvider() + ", but we don't like it.");
			        	}
			        }
			        else {
						//We have updated our position within the configured intervall, so don't do anything here...
			        	Log.e("gps service", "Got a new location from " + location.getProvider() + ", but last update was only " + ((double)timeSincelastUpdate)/60000 + " minutes ago.");
			        }
		    	}
			}

			public void onProviderDisabled(String provider) {}

			public void onProviderEnabled(String provider) {}

			public void onStatusChanged(String provider, int status, Bundle extras) {}

		};
		
		Context context = getApplicationContext();
		
        NotificationCompat.Builder mBuilder =
                new NotificationCompat.Builder(context)
        		.setContentTitle(getString(R.string.app_name))
        		.setContentText(getString(R.string.tracking))
                .setSmallIcon(R.drawable.location);
                
        // Creates an explicit intent for an Activity in your app
        Intent notificationIntent = new Intent(this, MapViewActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);


        // Adds the Intent that starts the Activity to the top of the stack
        mBuilder.setContentIntent(pendingIntent);

        Notification notification = mBuilder.build();
		startForeground(ID, notification);
	}
	
	/**
	 * ok the position was good, so save it and send it to the server
	 * 
	 * @param location the position we want so save
	 */
	private void update(Location location) {
		lastUpdateTime = System.currentTimeMillis();
        mCurrentLocation.set(location);
		// send the position to the server!
		ServerCommunication.updateGPS(location.getLatitude(), location.getLongitude(), this);
	}

	
	/**
	 * This method is called to start the location listeners or to update them.
	 * when the map view is in foreground, we also start a gps listener, otherwise only a network listener
	 * when we close the map view activity, we stop the gps listener.
	 * We update the listener to use minTime and minDistance as the user has set in preferences
	 * 
	 * @param mapInForeground wether the mapview is in foreground (true) or not (false)
	 */
    public void updateLocationListener(boolean mapInForeground){
    	inMapView = mapInForeground;
    	mlocManager.removeUpdates(mlocListener);
    	
    	Context context = getApplicationContext();
    	SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
    	inGpsMode = sharedPref.getBoolean("gps_mode", false);
    	
    	if(inGpsMode || inMapView) {
    		// OK we are in gps mode or the Map is in foreground!
    		Log.d("gps service", "GPS and network now with intervall 5s / 1m");
    		mlocManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, 5000, 1, mlocListener);
    		mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 5000, 1, mlocListener);
    	}
    	else {
    		float intervall = Float.parseFloat(sharedPref.getString("track_frequency", "20"));
	    	long frequency = Long.parseLong(sharedPref.getString("sync_frequency", "60000"));
	    	if(frequency<3600000) {
	    		mlocManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, frequency, intervall, mlocListener);
	    		Log.d("gps service", "ONLY network now with intervall " + frequency / 1000 + "s / " + intervall + "m");
	    	}
	    	else {
	    		mlocManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, 3600000, 0, mlocListener);
	    		Log.d("gps service", "ONLY network now with intervall 1h / 0m");
	    	}
    	}
    }
	
	@Override
	public void onDestroy() {
		mlocManager.removeUpdates(mlocListener);
	}
	
	@Override
	/**
	 * Request updates from network coordinates.
	 * Store them on our server every time they change.
	 */
	public void onStart(Intent intent, int startId) {
		
		updateLocationListener(false);
		
	}

}
